// find ./example -type f -name "*.cpp" -o -name "*.h" | xargs -n 1 ./bom

#include <iostream>
#include <fstream>
#include <string.h>

int main(int argc, const char* argv[])
{
    using namespace std;

    const int N = 10 * 1024 * 1024;
    char * buf = new char[N];
    unsigned char* lpuBuf = (unsigned char*)buf;

    int nFileSize = 0;

    const char* lpszFile = 0;
    bool bNeedSave = false;
    bool bHasBom = false;
    bool bAddBom = false;

    int nRet = 1;
    int ret = 0;

    cout << "argc = " << argc << endl;
    cout << "argv[0] = " << argv[0] << endl;

    if ((0 == ret) && (2 == argc))
    {
        lpszFile = argv[1];
        ifstream in( lpszFile, ios::binary );
        if (in.is_open())
        {
            in.seekg(0, ios::end);
            nFileSize = in.tellg();
            in.seekg( 0, ios::beg );
            in.read( buf, N );
            in.close();
            cout << "open file success = " << lpszFile << endl;
            cout << "file size = " << nFileSize << endl;
        }
        else
        {
            cout << "open file failed = " << lpszFile << endl;
            ret = 1;
        }
    }

    if ( (0 == ret) && ( nFileSize < 3 ) )
    {
        ret = 1;
    }

    if( 0 == ret )
    {
        bHasBom = ( 0xEF == lpuBuf[0] ) && ( 0xBB == lpuBuf[1] ) && ( 0xBF == lpuBuf[2] );
    }

    // add bom
    if( 0 == ret )
    {
        if( bAddBom && !bHasBom )
        {
            memmove( buf + 3, buf, nFileSize );
            nFileSize += 3;
            lpuBuf[0] = 0xEF;
            lpuBuf[1] = 0xBB;
            lpuBuf[2] = 0xBF;
            bNeedSave = true;
        }
        if( !bAddBom && bHasBom )
        {
            cout << lpszFile << " has bom, need remove" << endl;
            memmove( buf, buf+3, nFileSize-3 );
            nFileSize -= 3;
            bNeedSave = true;
        }
    }

    // 保存文件
    if( bNeedSave )
    {
        ofstream out( lpszFile, ios::binary );
        out.write( buf, nFileSize );
        out.flush();
        out.close();
        nRet = 0;
        ret = 1;
    }

    if (0 == nRet)
    {
        cout << lpszFile << " -- remove bom" << endl;
    }
    else
    {
        cout << lpszFile << " -- no bom" << endl;
    }

    delete[] buf;
    buf = 0;

    return nRet;
}
